/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package uit.ieproject.utilites;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jvntokenizer.PennTokenizer;
import uit.ieproject.business.ActivityBLO;
import uit.ieproject.business.PersonBLO;
import uit.ieproject.business.RegexBLO;
import uit.ieproject.entities.Activity;
import uit.ieproject.entities.Regex;

/**
 *
 * @author Maivia
 */
public class ExtractUtil {

    public static String getCorrectDeathYear(String birthday, String death) {
        Pattern pattern = Pattern.compile("[0-9]{3,4}");
        Matcher matcher = pattern.matcher(birthday);
        while (matcher.find()) {
            String year = matcher.group();
            death = year.substring(0, 2) + death;
            return death;
        }
        return death;
    }

    public static boolean isValidBirthday(String birthday) {
        Pattern pattern1 = Pattern.compile("^((\\p{Lu}\\p{Ll}+)\\s)((\\p{L}+)\\s)\\d");
        Pattern pattern2 = Pattern.compile("^(\\d|\\.|\\|/|-)+");
        Matcher matcher = pattern1.matcher(birthday);
        while (matcher.find()) {
            return true;
        }
        matcher.usePattern(pattern2);
        while (matcher.find()) {
            return true;
        }
        return false;
    }

    public static String getCorrectBirthday(String birthday) {
        Pattern pattern = Pattern.compile("(\\d{1,2}\\.\\d{1,2}\\.)?\\d{3,4}");
        Matcher matcher = pattern.matcher(birthday);
        while (matcher.find()) {
            birthday = matcher.group();
            return birthday;
        }
        return birthday;
    }

    public static boolean isValidActivity(String activity) {
        boolean isValid = false;
        if (!activity.startsWith(".") && !activity.startsWith("(") && !activity.startsWith(")") && !activity.startsWith(",") && !activity.startsWith("-") && activity.length() > 15) {
            isValid = true;
        }
        return isValid;
    }

    public static String getCorrectHometown(String hometown) {
        if (hometown.charAt(hometown.length() - 1) == ',') {
            hometown = hometown.substring(0, hometown.length() - 2).trim();
        }
        return hometown;
    }

    public static ArrayList<String> getQuerySentencesFromQuestion(String question) throws SQLException {
        ArrayList<String> answers = new ArrayList<>();  //Index 0: name         Index>0:answers
        String name = "";
        String mainType = "";
        ArrayList<String> questionTypes = new ArrayList<>();
        ArrayList<String> activityTimes = new ArrayList<>();
        question = formatQuestion(question);
        RegexBLO regexBLO = new RegexBLO();
        ArrayList<Regex> questionRegexs = regexBLO.getRegex(Info.ALL_TYPE, Info.QA_TYPE, 1);
        int numRegexs = questionRegexs.size();
        if (numRegexs > 0) {
            if (question.contains(",")) {
                //question contain ',' char
                String[] sentences = question.split(",");
                int i = 0;
                while (i < sentences.length) {
                    String sentence = sentences[i].trim();
                    if (!sentence.isEmpty()) {
                        ArrayList<String> results = getMatchesInfoFromQuestion(sentence, questionRegexs);
                        if (results.size() > 0) {
                            if (name.isEmpty()) {
                                name = results.get(0);
                            }
                            String type = results.get(1);
                            type = getColumnName(type, 0);
                            if (!type.equals(Info.ACTIVITY_REGEX)) {
                                questionTypes.add(type);
                            } else {
                                String time = results.get(2);
                                activityTimes.add(time);
                            }
                            mainType = type;
                            sentences[i] = "";
                            i = -1;
                        } else {
                            //Not understand question yet:
                            if (!name.isEmpty()) {
                                int steps = 1;
                                while (steps < 5) {
                                    String temp = getFullySentence(sentence, name, steps, mainType);
                                    results = getMatchesInfoFromQuestion(temp, questionRegexs);
                                    if (results.size() > 0) {
                                        String type = results.get(1);
                                        type = getColumnName(type, 0);
                                        if (!type.equals(Info.ACTIVITY_REGEX)) {
                                            questionTypes.add(type);
                                        } else {
                                            String time = results.get(2);
                                            activityTimes.add(time);
                                        }
                                        sentences[i] = "";
                                        break;
                                    }
                                    steps++;
                                }
                            }
                        }
                    }
                    i++;
                }
            } else {
                //Simple sentence
                ArrayList<String> results = getMatchesInfoFromQuestion(question, questionRegexs);
                if (results.size() > 0) {
                    name = results.get(0);
                    String type = results.get(1);
                    if (!type.equals(Info.ACTIVITY_REGEX)) {
                        type = getColumnName(type, 0);
                        questionTypes.add(type);
                    } else {
                        String time = results.get(2);
                        activityTimes.add(time);
                    }
                }
            }
        } else {
            //Not Have any regexs
        }

        if (!name.isEmpty() && (questionTypes.size() > 0 || activityTimes.size() > 0)) {
            //have the answers  
            answers.add(getFormatName(name));
            ArrayList<String> temp = getAnswerByQuery(name, questionTypes, activityTimes);
            for (int j = 0; j < temp.size(); j++) {
                answers.add(temp.get(j));
            }
        }
        return answers;
    }

    public static String getColumnName(String type, int language) {
        if (language == 0) {
            switch (type) {
                case Info.NAME_REGEX:
                    type = "birthday";
                    break;
                case Info.DEATH_REGEX:
                    type = "died";
                    break;
                case Info.HOMETOWN_REGEX:
                    type = "hometown";
                    break;
                case Info.NICKNAME_REGEX:
                    type = "nickname";
                    break;
                case Info.REALNAME_REGEX:
                    type = "realname";
                    break;
                case Info.FATHER_REGEX:
                    type = "father";
                    break;
                case Info.MOTHER_REGEX:
                    type = "mother";
                    break;
            }
        } else {
            switch (type) {
                case "birthday":
                    type = Info.NAME_REGEX;
                    break;
                case "died":
                    type = Info.DEATH_REGEX;
                    break;
                case "hometown":
                    type = Info.HOMETOWN_REGEX;
                    break;
                case "nickname":
                    type = Info.NICKNAME_REGEX;
                    break;
                case "realname":
                    type = Info.REALNAME_REGEX;
                    break;
                case "father":
                    type = Info.FATHER_REGEX;
                    break;
                case "mother":
                    type = Info.MOTHER_REGEX;
                    break;
            }
        }
        return type;
    }

    public static String getFormatName(String name) {
        String formatName = "";
        String[] temp = name.split("\\s");
        for (int i = 0; i < temp.length; i++) {
            Character firstChar = temp[i].charAt(0);
            formatName += firstChar.toString().toUpperCase() + temp[i].substring(1, temp[i].length());

            if (i != temp.length - 1) {
                formatName += " ";
            }
        }

        return formatName;
    }

    public static ArrayList<String> getAnswerByQuery(
            String name, ArrayList<String> questionTypes, ArrayList<String> activityTimes) throws SQLException {
        PersonBLO personBLO = new PersonBLO();
        ActivityBLO activityBLO = new ActivityBLO();
        ArrayList<String> answers = new ArrayList<>();
        StringBuilder sql = new StringBuilder();
        if (questionTypes.size() > 0) {
            for (int i = 0; i < questionTypes.size(); i++) {
                String type = questionTypes.get(i);

                sql.append("SELECT ");
                sql.append(type);
                sql.append(" FROM ");
                sql.append(Info.TABLE_PERSON);
                sql.append(" WHERE name LIKE N'").append(name).append("'");

                StringBuilder answerBuilder = new StringBuilder();
                String answer = personBLO.getAnswerAboutPerson(sql.toString());
                answerBuilder.append(getColumnName(type, 1)).append(" của ").append(getFormatName(name)).append(" : ").append(answer);

                answers.add(answerBuilder.toString());
                sql.setLength(0);
            }

        }
        if (activityTimes.size() > 0) {
            long id = personBLO.getIdByName(name);
            ArrayList<Activity> activities = activityBLO.getAllActivitiesOfPerson(id);
            sortActivitiesByTime(activities);
            if (id != 0) {
                for (int i = 0; i < activityTimes.size(); i++) {
                    String time = activityTimes.get(i);
                    ArrayList<Integer> yearsInQuestion = getYearsFromString(time);
                    try {
                        String answer = getAnswerAboutActivity(activities, yearsInQuestion);
                        answers.add(answer);
                    } catch (Exception ex) {
                    }
                }
            }
        }
        return answers;
    }

    public static String formatQuestion(String question) {
        question = question.replaceAll("\\bvà\\b", ",");
        question = question.replaceAll(";", ",");
        question = question.replaceAll("\\.", ",");
        question = PennTokenizer.tokenize(question);
        question = question.toLowerCase();
        return question;
    }

    public static String getFullySentence(String sentence, String name, int step, String mainType) {
        Pattern pattern = Pattern.compile(Info.PREFFIX_REGEX);
        Matcher matcher = pattern.matcher(sentence);
        while (matcher.find()) {
            String matches = matcher.group();
            sentence = sentence.replaceAll(name, matches);
            return sentence;
        }

        if (step == 1) {
            if (!sentence.contains(name)) {
                sentence = name + " " + sentence;
            }
        }
        if (step == 2) {
            if (!sentence.contains(name)) {
                sentence = sentence + " của " + name;
            }
        }
        if (mainType.equals(Info.ACTIVITY_REGEX)) {
            if (step == 3) {
                if (!sentence.contains(name)) {
                    sentence = sentence + " " + name + " làm gì";
                }
            }
            if (step == 4) {
                if (!sentence.contains(name)) {
                    sentence = name + " làm gì " + sentence;
                }
            }
        }
        return sentence;
    }

    public static ArrayList<String> getMatchesInfoFromQuestion(String question, ArrayList<Regex> questionRegexs) {
        ArrayList<String> results = new ArrayList<>();
        Pattern pattern;
        Matcher matcher;
        int size = questionRegexs.size();
        for (int i = 0; i < size; i++) {
            Regex regex = questionRegexs.get(i);
            String expression = regex.getExpression();
            pattern = Pattern.compile(expression);
            matcher = pattern.matcher(question);
            if (matcher.matches()) {
                String personName = matcher.group(Info.NAME_GROUP).trim();
                String regexName = regex.getName().trim();
                results.add(personName);
                results.add(regexName);
                if (regexName.equals(Info.ACTIVITY_REGEX)) {
                    String time = "all";
                    if (matcher.group(Info.TIME_GROUP) != null && matcher.group(Info.TIME_GROUP).trim().length() > 0) {
                        time = matcher.group(Info.TIME_GROUP).trim();
                    }
                    results.add(time);
                }
            }
        }
        return results;
    }

    public static ArrayList<Integer> getYearsFromString(String time) {
        ArrayList<Integer> results = new ArrayList<>();
        if (time.equals("all")) {
            results.add(0);
            return results;
        }
        Pattern pattern = Pattern.compile("[0-9]{3,4}");
        Matcher matcher = pattern.matcher(time);
        while (matcher.find()) {
            results.add(Integer.valueOf(matcher.group().trim()));
        }
        int size = results.size();
        if (size == 1 || (size == 2 && results.get(0) <= results.get(1))) {
            if (size == 2 && results.get(0) == results.get(1)) {
                results.remove(1);
            }
            return results;
        } else {
            return null;
        }
    }

    public static String getAnswerAboutActivity(ArrayList<Activity> activities, ArrayList<Integer> times) {
        StringBuilder answer = new StringBuilder();
        int numActivities = activities.size();
        int numTimes = times.size();
        for (int i = 0; i < numActivities; i++) {
            Activity activity = activities.get(i);
            String time = activity.getTime();
            String act = activity.getAct();
            act = act.replaceAll("[^\\p{L}]\\s", "");
            ArrayList<Integer> timesInActivity = getYearsFromString(time);
            if (timesInActivity != null) {
                int numTimesInActivity = timesInActivity.size();
                if (numTimes == 1) {    //just 1 year in question
                    int timeInQuestion = times.get(0);
                    if (timeInQuestion == 0) {  //all
                        answer.append(time).append(" : ");
                        answer.append(act);
                        answer.append("\n");
                    } else {  //specify year
                        if (numTimesInActivity == 1) {
                            if (timesInActivity.get(0) == timeInQuestion) {
                                answer.append(time).append(" : ");
                                answer.append(act);
                                answer.append("\n");
                            }
                        } else {  //2
                            if (timesInActivity.get(0) == timeInQuestion || timesInActivity.get(1) == timeInQuestion) {
                                answer.append(time).append(" : ");
                                answer.append(act);
                                answer.append("\n");
                            }
                        }
                    }
                } else {    // 2 years in Question
                    int startTimeInQuestion = times.get(0);
                    int endTimeInQuestion = times.get(1);
                    if (numTimesInActivity == 1) {
                        if (timesInActivity.get(0) >= startTimeInQuestion && timesInActivity.get(0) <= endTimeInQuestion) {
                            answer.append(time).append(" : ");
                            answer.append(act);
                            answer.append("\n");
                        }
                    } else {
                        if (timesInActivity.get(0) >= startTimeInQuestion && timesInActivity.get(1) <= endTimeInQuestion) {
                            answer.append(time).append(" : ");
                            answer.append(act);
                            answer.append("\n");
                        }
                    }
                }
            }
        }
        return answer.toString();
    }

    public static void sortActivitiesByTime(ArrayList<Activity> unsortedActivities) {
        int currentSize = unsortedActivities.size();
        for (int i = 0; i < currentSize - 1; i++) {
            for (int j = i + 1; j < currentSize; j++) {
                String time1 = unsortedActivities.get(i).getTime();
                String time2 = unsortedActivities.get(j).getTime();
                if (compareTwoTimes(time1, time2) > 0) {    //time2<time1
                    swapActivities(unsortedActivities, i, j);
                }
            }
        }
    }

    public static void swapActivities(ArrayList<Activity> activities, int i, int j) {
        Activity temp = activities.get(i);
        activities.set(i, activities.get(j));
        activities.set(j, temp);
    }

    public static int compareTwoTimes(String timeStr1, String timeStr2) {
        int time1 = 0;
        int time2 = 0;
        Pattern pattern = Pattern.compile("[0-9]{3,4}");
        Matcher matcher = pattern.matcher(timeStr1);
        while (matcher.find()) {
            time1 = Integer.valueOf(matcher.group().trim());
        }
        matcher = pattern.matcher(timeStr2);
        while (matcher.find()) {
            time2 = Integer.valueOf(matcher.group().trim());
        }
        if (time1 > time2) {
            return 1;
        } else if (time1 == time2) {
            return 0;
        } else {
            return -1;
        }
    }

    public static String formatYear(String time, String regex) {
        String formatedTime = time;
        if (time.contains(regex)) {
            String[] arrYear = time.split(regex);
            if (arrYear.length == 2) {
                if (arrYear[0].trim().length() >= 4 && arrYear[1].trim().length() == 2) {
                    formatedTime = arrYear[0].trim() + " " + regex + " " + "19" + arrYear[1].trim();
                }
            }
        }
        return formatedTime;
    }
}
